#include "Render.h"
#include "Model.h"

#include "SpriteNode.h"
#include "TextNode.h"

extern HINSTANCE g_hInst;
extern HWND g_wndHandle;

void Render::Init()
{
	//store model pointer
	model = Model::getInstance();

	//init texture numbers
	maxTextures = NUM_SPRITES;
	numTextures = 0;

	//direct3d
	pD3D = Direct3DCreate9(D3D_SDK_VERSION);

	ZeroMemory( &d3dpp, sizeof(d3dpp) );
	d3dpp.Windowed = TRUE;
	d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
	d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
	d3dpp.BackBufferCount  = 1;
	d3dpp.BackBufferHeight = SCREEN_HEIGHT;
	d3dpp.BackBufferWidth  = SCREEN_WIDTH;
	d3dpp.hDeviceWindow    = g_wndHandle;
	
	SetWindowLong(d3dpp.hDeviceWindow, GWL_STYLE, WS_OVERLAPPEDWINDOW);
	SetWindowPos(d3dpp.hDeviceWindow, HWND_TOP, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
	
	pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, g_wndHandle, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pd3dDevice);
    
	pd3dDevice->SetRenderState(D3DRS_LIGHTING, FALSE);

	
	//Create a sprite object
	D3DXCreateSprite(pd3dDevice, &sprite);

	//create font objects
	D3DXCreateFont(pd3dDevice, 25, 0, FW_DONTCARE, 0, false, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, TEXT("Arial"), &Font[SMALL]);
	D3DXCreateFont(pd3dDevice, 90, 0, FW_DONTCARE, 0, false, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, TEXT("Arial"), &Font[MEDIUM]);
	D3DXCreateFont(pd3dDevice, 160, 0, FW_DONTCARE, 0, false, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, TEXT("Arial"), &Font[LARGE]);
}

int Render::LoadTexture(char* path)
{
	if(numTextures >= maxTextures)
		return -1;
	D3DXCreateTextureFromFileEx(pd3dDevice, path, D3DX_DEFAULT_NONPOW2, D3DX_DEFAULT_NONPOW2, 0, 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, D3DCOLOR_XRGB(255, 0, 255), 0, 0, &texture[numTextures]);
	numTextures++;
	return numTextures;
}

int Render::LoadTexture(char* path, int sizeX, int sizeY)
{
	if(numTextures >= maxTextures)
		return -1;
	D3DXCreateTextureFromFileEx(pd3dDevice, path, sizeX, sizeY, 0, 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, D3DCOLOR_XRGB(255, 0, 255), 0, 0, &texture[numTextures]);
	numTextures++;
	return numTextures-1;
}

void Render::AddToDrawList(DrawNode* node)
{
	list.push(node);
}

void Render::RenderFrame()
{
	DrawNode* newNode;

	//Create list
	model->Draw();

	pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0 );
	pd3dDevice->BeginScene();

	//draw list
	newNode = list.pop();
	while(newNode)
	{
		switch(newNode->getColor())
		{
		//assign correct d3dcolor to color
		case WHITE:	color = D3DCOLOR_XRGB(255,255,255);	break;
		case RED:	color = D3DCOLOR_XRGB(255,0,0);		break;
		case GREEN:	color = D3DCOLOR_XRGB(0,255,0);		break;
		case BLUE:	color = D3DCOLOR_XRGB(0,0,255);		break;
		case GRAY:	color = D3DCOLOR_XRGB(100,100,100);	break;
		default:	color = D3DCOLOR_XRGB(255,255,255);	break;
		};

		switch(newNode->getType())
		{
		case INVALID_NODE:	break;
		case TEXT:		renderText((TextNode*)newNode);	break;
		case SPRITE:	renderSprite((SpriteNode*)newNode);	break;
		};
		newNode = list.pop();
	}

	pd3dDevice->EndScene();
	pd3dDevice->Present( NULL, NULL, NULL, NULL );
}

void Render::renderText(TextNode* node)
{
	XY pos = node->getPos();
	RECT rect = node->getRect();
	FontSize size = node->getSize();
	char* message = node->getString();
	
	Font[size]->DrawText(0, message, -1, &rect, DT_VCENTER | DT_CENTER | DT_NOCLIP, color);
}

void Render::renderSprite(SpriteNode* node)
{
	XY pos = node->getPos();
	float dir = (float)node->getOrientation();
	int tex = node->getTexture();
	XY scale = node->getScale();

	D3DXMatrixIdentity(&spriteMat);
	D3DXMatrixIdentity(&spriteScale);
	D3DXMatrixIdentity(&spriteRotate);
	D3DXMatrixIdentity(&spriteTranslate);

	//Begin drawing the sprite
	sprite->Begin(D3DXSPRITE_ALPHABLEND | D3DXSPRITE_SORT_DEPTH_FRONTTOBACK);

	D3DXMatrixTranslation(&spriteTranslate, (float)pos.x, (float)pos.y, 0.0f);
	D3DXMatrixRotationZ(&spriteRotate, D3DXToRadian(dir));
	D3DXMatrixScaling(&spriteScale, (float)scale.x, (float)scale.y, 0);

	D3DXMatrixMultiply(&spriteScale, &spriteScale, &spriteRotate);		//Multiply scale and rotation, stored in scale
	D3DXMatrixMultiply(&spriteMat, &spriteScale, &spriteTranslate);		//Multiply scale and translation, stored in world
	
	//Set the transform
	sprite->SetTransform(&spriteMat);

	//Draw the sprite object with the texture
	sprite->Draw(texture[tex], 0, &D3DXVECTOR3( 0.0f, 0.0f, 0.0f), 0, color);

	//End drawing the sprite
	sprite->End();
}
